<?php

namespace app\command;

use app\common\lib\Common;
use app\exception\IndexException;
use app\model\cron\CronTask;
use bootstrap\DBListen;
use support\Cache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Webman\Config;
use Webman\Event\Event;


class CronIndex extends Command
{
    protected static $defaultName = 'cron:index';
    protected static $defaultDescription = 'cron index';

    /**
     * @return void
     */
    protected function configure()
    {
        //发布执行结束
        Event::dispatch('console.start', []);

        //$this->addArgument('name', InputArgument::OPTIONAL, 'Name description');

        Common::initTaskConfig();
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        try{

            //        $name = $input->getArgument('name');
            //        $output->writeln('Hello cron:index');
            $this->autoGenerate();

            return self::SUCCESS;
        }catch (\Throwable $e){
           Common::consoleExecptionReport('php webman '.self::$defaultName,$e);
           return self::FAILURE;
        }


    }

    public function autoGenerate()
    {
        //todo 1 检查任务文件是否改动
        $isstart = false;
        $cacheKey = config('app.app_name','video').'job_cron_filetime';
        $cacheTableKey = config('app.name','video').'job_cron_tabletime';

        $fileTimeData = Cache::get($cacheKey);

        $dirPath = app_path('command');
        $fileTimeMap = [];
        $dirDatas = scandir($dirPath);
        //$crontabFile = config_path('crontab.php');
        //array_unshift($dirDatas,$crontabFile);

        foreach ($dirDatas as $file){
            $file = is_file($file) ? $file : $dirPath.DIRECTORY_SEPARATOR.$file;
            if(is_file($file)){
                $key = md5($file);
                $fileTimeMap[$key] = filemtime($file);
                if(!isset($fileTimeData[$key])){
                    $isstart = true;
                }elseif($fileTimeMap[$key]!=$fileTimeData[$key]){
                    $isstart = true;
                }
            }
        }

        //有所改动就重新启动workerman
        $updateTimes = [];
        if($isstart===false){
            //todo 2 检查数据库任务表数据是否改动
            $tableTimeMap = Cache::get($cacheTableKey);

            $updateTimes = CronTask::getInstance()->getWhere([['cronid','>',0]])->pluck('updated_at','cronid')->toArray();
            foreach($updateTimes as $cronid=>$time){
                if(!isset($tableTimeMap[$cronid])){
                    $isstart = true;
                }elseif($time != $tableTimeMap[$cronid]){
                    $isstart = true;
                }
            }
        }

        //有所改动就重新启动workerman
        if($isstart===true){
            //数据库改动就要重新生成配置文件
            $this->genCrontabConfigFile();

            $fileTimeMap && Cache::set($cacheKey,$fileTimeMap);
            $updateTimes && Cache::set($cacheTableKey,$updateTimes);
        }

        //var_dump($isstart);
        return 'success';
    }

    public function genCrontabConfigFile()
    {
        $date = date('Y/m/d');
        $time = date('H:i:s');
        $context ="<?php\n/**\n* 定时任务配置文件\n* User: kela* Date: $date\n* Time: $time\n*/\n\n";
        $context .= "  return [\n";
        //        $context .= "   'restart_workerman' => [\n";
        //        $context .= "         'worker_id' => 1, // 需要绑定的进程id. 一共有设有4个进程，选择一个进程跑\n";
        //        $context .= "         'time' => 10, // 如果是数字 ，意思是间隔多少秒跑一次。 如果是 5 * * * * * crontab模式 类似于cron形式走\n";
        //        $context .= "         'callback' => [app(\App\Http\Controllers\Cron\IndexController::class),'index']\n";
        //        $context .= "   ],\n\n";
        $data = CronTask::getInstance()->getWhere(['status'=>1])->orderBy('cronid','asc')->get();

        foreach($data as $val){
            if(!$val['is_callback']){
                $callback = "'".$val['cmd']."'"; //'function(){ exec(\''.$val['cmd'].'\', $output); return $output;}';
            }else{
                $callback = "'".$val['cmd']."'";
            }
            $key = str_replace([':',' ','  ','-'],['_','_','_','_'],strtolower($callback));

            $context .= "  //{$val['remark']}\n";
            $context .= "  $key => [\n";
            $context .= "       'worker_id' => {$val['worker_id']},\n";
            $context .= "       'time' => '{$val['cron_expression']}',\n";
            $context .= "       'callback' => $callback,\n";
            $context .= "       'param' =>'{$val['param']}',\n";
            $context .= "       'cronid' =>'{$val['cronid']}',\n";
            $context .= "  ],\n\n";


        }
        $context .=  "];";
        file_put_contents(runtime_path('crontab.php'),$context);

        return true;
    }

}
